home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 4 / MacMania 4.toast / / Demo's / Igor Demo Pro / 3 PutContentsIn Igor Pro Folder / Technical Notes / Igor Tech Notes / TN020-A Custom Peak Meas / Custom Peak Measurement Folder / procedure next >
Text File  |  1993-09-24  |  29KB  |  1,205 lines

  1. | Custom Peak Measurement Experiment V1.3 - 7/15/93
  2. Menu "Macros"
  3.     m_so
  4.     m_mp
  5.     "-"
  6.     Submenu m_b
  7.         m_bi
  8.         m_ba
  9.         m_bd
  10.         m_bf
  11.         m_s
  12.         m_bs
  13.     End
  14.     Submenu m_f
  15.         m_ii
  16.         m_ia
  17.         m_id
  18.         m_iap
  19.         "-"
  20.         m_ff
  21.         "-"
  22.         m_fr
  23.         m_fs
  24.         m_fh
  25.         m_s
  26.     End
  27.     "-"
  28.     m_cug
  29.     m_cw
  30. End
  31. Macro MakePeaks(py,noise,minx,maxx,log,pts)
  32.     String py=g_w
  33.     Variable noise=mp_noise,log=mp_log,pts=mp_pnts,minx=mp_minx,maxx=mp_maxx
  34.     Prompt py,"Output wave name"
  35.     Prompt noise,"peak wave noise (enoise val)"
  36.     Prompt minx,"starting x value"
  37.     Prompt maxx,"ending x value"
  38.     Prompt log,"x wave increment",popup,"linear;logarithmic"
  39.     Prompt pts,"points in output waves",popup,p_pts
  40.  
  41.     Silent 1;PauseUpdate
  42.     mp_noise=noise;mp_log=log;mp_pnts=pts;mp_minx=minx;mp_maxx=maxx
  43.     String ctrX="W_MakeCentersX",ampY="W_MakeAmpsY",widthX="W_MakeWidthsX",px
  44.     String cw="W_MyPkCoefs",wtmp="W_tmp"
  45.     Variable kk1,kk3,last=strlen(py)-1,n=2^pts,npks
  46.     if(cmpstr("y",py[last])==0)
  47.         last-=1
  48.     endif
  49.     px=py[0,last]+"X"
  50.     Mk(py,n);Mk(px,n);$py=0
  51.     SetScale x,minx,maxx,$py,$px
  52.     if(log==2)
  53.         $px=minx*(maxx/minx)^(p/n)
  54.     else
  55.         $px=x
  56.     endif
  57.     WaveStats/Q $ctrX;npks=V_npnts
  58.     iterate (npks)
  59.         n= MyPeakSizesToCoefs($ctrX[i],$ampY[i],$widthX[i],W_My[i],$cw)    |  output cw, for initial guesses
  60.         $py+=MyPeak($cw,$px[p])
  61.     loop
  62.     $py+=enoise(noise)
  63.     g_w=py
  64.     if(log==2)
  65.         g_wx=px
  66.         AppWv(py,px,"")
  67.     else
  68.         g_wx=calc
  69.         AppWv(py,"","")
  70.     endif
  71. EndMacro
  72.  
  73. Macro InitializeMostEverything(w,wx,wb)
  74.     String w=g_w,wx=g_wx,wb=g_b
  75.     Prompt w,p_w,popup, WaveList("*",";","")
  76.     Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
  77.     Prompt wb,p_b,popup, none+WaveList("*base*",";","")
  78.  
  79.     Silent 1;PauseUpdate
  80.     g_w=w;g_wx=wx; SBs(wb)
  81.     Redimension/D $w
  82.     SameLen(w,breg);$breg=NaN
  83.     Mk(ampsY,2);Mk(ctrsX,2);Mk(widsX,2);Mk(ctrsP,2);Mk(edgsP,4);
  84.     Mk(areaNB,2);Mk(areaX1,2);Mk(areaX2,2);
  85.     Mk(bdcw,2);Mk(pdcw,2)
  86.     Mk("W_MyPkCoefs",4) | MyPeak cw[0,3]
  87.     if(exists(wx)==1)
  88.         Redimension/D$wx
  89.     endif
  90.     if(exists(wb)==1)
  91.         Redimension/D $wb
  92.     endif
  93.     AppWv(w,wx,"");HideFittedPeaks()
  94. End
  95.  
  96. Macro InitBaseLineFit(w,wx)
  97.     String w=g_w,wx=g_wx
  98.     Prompt w,p_w,popup, WaveList("*",";","")
  99.     Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
  100.     
  101.     Silent 1;PauseUpdate
  102.     g_w=w;g_wx=wx
  103.     SameLen(w,breg);AppWv(breg,wx,"");Modify mode($breg)=1;$breg=NaN;AppCrs(w)
  104. End
  105. Macro AddRegionToFit()
  106.     Silent 1;PauseUpdate
  107.     CheckTwoCursors(g_w);$breg[V_start,V_theEnd]=$g_w[p]
  108. End
  109. Macro DeleteRegionFromFit()
  110.     Silent 1;PauseUpdate
  111.     CheckTwoCursors(g_w);$breg[V_start,V_theEnd]=NaN
  112. End
  113.  
  114. Macro FitBaselineAtRegions(w,wx,wr,fit)
  115.     String w=g_w,wx=g_wx,wr=fbar_wr,fit=fbar_fit
  116.     Prompt w,p_w,popup, WaveList("*",";","")
  117.     Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
  118.     Prompt wr,"region wave (baseline weighting wave)",popup, none+breg
  119.     Prompt fit,"baseline function",popup,S_funcs
  120.     
  121.     Silent 1;PauseUpdate
  122.     g_w=w;g_wx=wx;fbar_wr=wr;fbar_fit=fit
  123.     ChkLen(w,wx);ChkLen(w,wr)
  124.     String ow="W_BaselineFit",wtmp="W_tmp",opts="";SameLen(w,ow)
  125.     Variable t=0,typ=floor(strsearch(S_funcs,fit,0)/10)
  126.     
  127.     if(exists(wx)==1)
  128.         opts+="/X="+wx
  129.     endif
  130.     if(exists(wr)==1)
  131.         Dup(wr,wtmp)
  132.         $wtmp=(numtype($wtmp)==0)
  133.         opts+="/W="+wtmp
  134.         ar_ex=3
  135.     else
  136.         ar_ex=1
  137.     endif
  138.     t=str2num(fit[7,8])-1
  139.     String command="CurveFit "+fit[1,7]+", $w"+opts
  140.     Execute command
  141.     KillWv(wtmp)
  142.     Mk(bcw,2);$bcw={NaN,K0,K1,K2,K3,K4};Redimension/N=(2+t) $bcw
  143.     Mk(bdcw,2);$bdcw={1,0,numpnts($w)-1,typ,t};Dup(bdcw,"W_PM")
  144.     if(exists(wx)==1)
  145.         $ow=PolyMorph($bcw,$wx[p])
  146.     else
  147.         $ow=PolyMorph($bcw,x)
  148.     endif
  149.     AppWv(ow,wx,"")
  150.     SBs(ow)
  151.     ar_wfit=ow
  152. End
  153.  
  154. Macro SubtractBaseline(w,wx,wb,ow)
  155.     String w=g_w,wx=g_wx,wb=rb_b,ow=rb_ow
  156.     Prompt w,p_w,popup, WaveList("*",";","")
  157.     Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
  158.     Prompt wb,p_b,popup, "_From Fit Peaks_;"+WaveList("*base*",";","")
  159.     Prompt ow,"output baseline-corrected wave",popup,new+WaveList("*",";","")
  160.  
  161.     Silent 1;PauseUpdate
  162.     g_w=w;g_wx=wx
  163.     ChkLen(w,wx);ChkLen(w,wb)
  164.     String cw,dcw,tcw="W_tmp0",tdcw="W_PM"
  165.     if(exists(ow)!=1)
  166.         NewWv(w,"NoBase");ow=S_Wave
  167.     else
  168.         SameLen(w,ow)
  169.     endif
  170.     rb_ow=ow
  171.     if(exists(wb)!=1)
  172.         cw=bcw
  173.         dcw=bdcw
  174.         if(numtype($dcw[1])!=0)
  175.             Abort "Run Fit Peaks first!"
  176.         endif
  177.         Variable terms=$dcw[4],s=$dcw[1],e=$dcw[2],funcs=$dcw[0]
  178.         Dup(cw,tcw);Redimension/N=(2+terms) $cw
  179.         Dup(dcw,tdcw);$tdcw[0]=1
  180.         wb="W_tmp";SameLen(w,wb);$wb=NaN
  181.         if(exists(wx)==1)
  182.             $wb[s,e]=PolyMorph($tcw,$wx[p])
  183.         else
  184.             $wb[s,e]=PolyMorph($tcw,x)
  185.         endif
  186.     endif
  187.  
  188.     $ow=$w-$wb
  189.     AppWv(ow,wx,"");Modify zero(left)=1
  190.     KillWv(wb);KillWv(tcw)
  191.     g_w=ow
  192.     SBs("_None_")
  193. End
  194.  
  195. Macro InitIdentifyPeaks(w,wx,wb,pol,box)
  196.     String w=g_w,wx=g_wx,wb=g_b
  197.     Variable box=g_bx,pol=mpr_pol
  198.     Prompt w,p_w,popup, WaveList("*",";","")
  199.     Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
  200.     Prompt wb,p_b,popup, none+WaveList("*base*",";","")
  201.     Prompt pol,"peak polarity", popup,"positive;negative"
  202.     Prompt box,p_bx
  203.     
  204.     Silent 1;PauseUpdate
  205.     g_w=w;g_wx=wx;SBs(wb)
  206.     box=abs(box);mpr_pol=pol;g_bx=box
  207.  
  208.     ChkLen(w,wx);ChkLen(w,wb)
  209.     Mk(ampsY,2);Mk(ctrsX,2);Mk(ctrsP,2);Mk(widsX,2);Mk(edgsP,4)
  210.     Mk("W_EstY",2) | MyPeak
  211.     DoWindow/F PeakFitGraph
  212.     if(V_Flag==0)
  213.         AppWv(w,wx,"");DoWindow/C PeakFitGraph
  214.     endif
  215.     AppWv(w,wx,"");AppWv(wb,wx,"")
  216.     ShowEdges();AppWv(ampsY,ctrsX,"");Modify mode($ampsY)=8,marker($ampsY)=18
  217.     AppCrs(w);HideFittedPeaks()
  218. End
  219.  
  220. Macro IdentifyPeakWithCursors()
  221.     Silent 1;PauseUpdate
  222.     String w=g_w,wx=g_wx,wb=g_b
  223.     CheckTwoCursors(w)
  224.     Variable s=V_start,en=V_theEnd,npks,ctr,box=g_bx,pol=mpr_pol
  225.     String wtmp="W_tmp",wtmp2="W_tmp2",e0="W_tmp0",e1="W_tmp1"
  226.     SplitEdges(e0,e1);npks=V_npnts
  227.     if(exists(wx)==1)
  228.         box *= sign($wx[en]-$wx[s])
  229.         FindPX(w,wx,box+$wx[s]);box=V_peakP
  230.         FindPX(w,wx,$wx[s]);box=abs(V_peakP-box)
  231.     else
  232.         box*=sign(rightx($w)-leftx($w))
  233.         box=x2pnt($w,box+leftx($w))
  234.     endif
  235.     box=max(1,box);Print "Averaging ",box," points..."
  236.     Duplicate/O/R=[s,en] $w,$wtmp;$wtmp=MyBoxSmooth($w,p+s,box)
  237.     WaveStats/Q $wtmp | Find peak's center pt
  238.     if(pol==1)
  239.         ctr=V_maxLoc
  240.     else
  241.         ctr=V_minLoc
  242.     endif
  243.     ctr=x2pnt($wtmp,ctr)+s
  244.     InsertPoints 0,1,$ctrsP,$ctrsX,$ampsY,$widsX,$e0,$e1
  245.     InsertPoints 0,1,W_EstY | MyPeak
  246.     InsertPoints 0,2,$edgsP
  247.     $ctrsP[0]=ctr
  248.     $e0[0]=s;$e1[0]=en
  249.     $ampsY[0]=$wtmp[ctr-s]
  250.     KillWv(wtmp);KillWv(wtmp2)
  251.     if(exists(wb)==1)
  252.         $ampsY[0]-=MyBoxSmooth($wb,ctr,box)
  253.     endif
  254.     if(exists(wx)==1)
  255.         $ctrsX[0]=$wx[ctr]
  256.     else
  257.         $ctrsX[0]=pnt2x($w,ctr)
  258.     endif
  259.     $widsX[0]=abs(V_theEndX-V_startX)
  260.     MergeEdges(e0,e1);ShowEdges()
  261. End
  262.  
  263. Macro DeletePksBetweenCursors()
  264.     Silent 1;PauseUpdate
  265.     String w=g_w,wx=g_wx,wb=g_b
  266.     CheckTwoCursors(w)
  267.     Variable s=V_start,en=V_theEnd,npks,ctr,box=g_bx,pol=mpr_pol
  268.     String wtmp="W_tmp",wtmp2="W_tmp2",e0="W_tmp0",e1="W_tmp1"
  269.     SplitEdges(e0,e1);npks=V_npnts
  270.     iterate (npks)
  271.         if(($ctrsP[i] >= s)%&($ctrsP[i] <= en))
  272.             $ctrsP[i]=NaN;$ctrsX[i]=NaN;$ampsY[i]=NaN;$widsX[i]=NaN
  273.             $e0[i]=NaN;$e1[i]=NaN;W_EstY[i]=NaN | MyPeak        
  274.         endif
  275.     loop
  276.     MergeEdges(e0,e1);ShowEdges()
  277.     if(V_npnts<1)
  278.         DoAlert 0, "no peaks left"
  279.     endif
  280. End
  281.  
  282. | Find peaks by analyzing peak data's smoothed derivatives (WARNING: sensitive to noise)
  283. Macro AutoIdentifyPeaks(what,w,wx,wb,mina,pol,box,extent,maxWidth)
  284.     String w=g_w,wx=g_wx,wb=g_b
  285.     Variable mina=fp_minamp
  286.     Variable what=tfp_what,pol=tfp_pol,box=g_bx,extent=tfp_extent,maxWidth=tfp_mw
  287.     Prompt what,"do what with found peaks?",popup, p_aipw
  288.     Prompt w,p_w,popup,WaveList("*", ";","")
  289.     Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
  290.     Prompt wb,p_b,popup,none+WaveList("*base*", ";","")
  291.     Prompt mina,"min pk amplitude, or 0 for auto-level"
  292.     Prompt pol,"peak polarity", popup,"positive;negative" 
  293.     Prompt box,p_bx
  294.     Prompt extent,"extent of Y wave to search",popup,"entire wave;between cursors"
  295.     Prompt maxWidth,"maximum peak x width (INF for no max)"
  296.  
  297.     Silent 1;PauseUpdate
  298.     tfp_what=what;g_w=w;g_wx=wx;SBs(wb)
  299.     box=abs(box)
  300.     tfp_pol=pol;g_bx=box;tfp_extent=extent
  301.     String cmd="FindAPeak",lvlw="W_ShowMinPkLvl"
  302.     ChkLen(w,wx);ChkLen(w,wb)
  303.     Variable s=0,en=numpnts($w)-1
  304.     if(extent==2) | use cursors
  305.         CheckTwoCursors(w)
  306.         s=V_start
  307.         en=V_theEnd
  308.     endif
  309.     if(exists(wx)==1)
  310.         box *= sign($wx[en]-$wx[s])
  311.         FindPX(w,wx,box+$wx[s]);box=V_peakP
  312.         FindPX(w,wx,$wx[s]);box=abs(V_peakP-box)
  313.     else
  314.         box*=sign(rightx($w)-leftx($w))
  315.         box=x2pnt($w,box+leftx($w))
  316.     endif
  317.     box=max(1,box);Print "Averaging ",box," points..."
  318.     if(mina==0)
  319.         Dup(w,lvlw)
  320.         if(exists(wb)==1)
  321.             $lvlw-=$wb
  322.         endif
  323.         Smooth 3, $lvlw
  324.         WaveStats/Q/R=[s,en] $lvlw
  325.         mina=V_sdev*0.5 |Heuristic
  326.         if (pol==2)
  327.             mina *= -1
  328.         endif
  329.         Print "Auto min peak amplitude = ",mina
  330.     endif
  331.     fp_minamp=mina
  332.     SameLen(w,lvlw);$lvlw=NaN
  333.     if(exists(wb)==1)
  334.         cmd+="/B="+wb
  335.         $lvlw[s,en]=mina+$wb[p]
  336.     else
  337.         $lvlw[s,en]=mina
  338.     endif
  339.     AppWv(lvlw,wx,"");ResumeUpdate
  340.     PauseUpdate
  341.     cmd+=" mina,pol,box,$w[rt,lf]"    |r=>l search
  342.     String e0="W_tmp0",e1="W_tmp1"
  343.  
  344.     if(what==2)
  345.         Mk(ampsY,2);Mk(ctrsX,2);Mk(ctrsP,2);Mk(widsX,2);Mk(edgsP,4);Mk("W_EstY",2) | MyPeak
  346.     endif
  347.  
  348.     Variable lf=s,rt=en,fl,ce,dX,npks=0
  349.     do
  350.         Execute cmd        | FindAPeak...
  351.         if(V_Flag==0)
  352.             | Insert a new Peak
  353.             InsertPoints 0,1,$ctrsP,$ctrsX,$ampsY,$widsX,W_EstY |MyPeak
  354.             InsertPoints 0,2,$edgsP
  355.             $ctrsP[0]=V_peakP
  356.             fl=floor(V_peakP);ce=ceil(V_peakP)
  357.             if(exists(wx)==1)    | convert f.p. V_peakP f.p. to wx coordinate
  358.                 if(fl != ce)
  359.                     dX=$wx[ce]-$wx[fl]
  360.                     $ctrsX[0]=$wx[fl]+(V_peakP-fl)*dX
  361.                 else
  362.                     $ctrsX[0]=$wx[V_peakP]
  363.                 endif
  364.             else
  365.                 $ctrsX[0]=V_peakX
  366.             endif
  367.             rt=fl-floor((box+1)/2)
  368.             npks+=1
  369.             Printf "%d...",npks
  370.         endif
  371.     while ((V_Flag==0) %& ((rt-lf)>1))
  372.     AppWv(ampsY,ctrsX,"");Modify mode($ampsY)=8,marker($ampsY)=18;ResumeUpdate
  373.     PauseUpdate
  374.     Printf "\r%d Peaks found...",npks
  375.     if(npks>0)
  376.         Printf "Estimating their sizes..."
  377.         cmd="EstimatePeakSizes"
  378.         if(exists(wx)==1)
  379.             cmd+="/X="+wx
  380.         endif
  381.         if(exists(wb)==1)
  382.             cmd+="/B="+wb
  383.         endif
  384.         cmd+="/E=$edgsP 50,maxWidth,box,npks,$ctrsP,$w,$ampsY,$widsX"
  385.         Execute cmd
  386.     endif
  387.     SplitEdges(e0,e1);MergeEdges(e0,e1)
  388.     Print "Done"
  389.     ShowEdges()
  390. End
  391.  
  392. Proc SplitEdges(e0,e1)
  393.     String e0,e1
  394.     Variable pts=numpnts($ctrsX)
  395.     Make/O/D/N=(pts) $e0,$e1;$e0=$edgsP[0+p*2];$e1=$edgsP[1+p*2]
  396.     WaveStats/Q $ctrsX | Count non-Nan peaks
  397. End
  398.  
  399. Proc MergeEdges(e0,e1)
  400.     String e0,e1
  401.     Sort $ctrsP,$ctrsX,$ampsY,$widsX,$e0,$e1;Sort $ctrsP,$ctrsP,W_EstY |MyPeak    | NaN's sorted to end of array
  402.     $edgsP[0,;2]=$e0[p/2]
  403.     $edgsP[1,;2]=$e1[(p-1)/2]
  404.     KillWaves $e0,$e1
  405.     WaveStats/Q $ctrsX
  406.     Redimension/N=(V_npnts+2) $ctrsP,$ctrsX,$ampsY,$widsX,W_EstY | MyPeak
  407.     Redimension/N=((V_npnts+2)*2) $edgsP
  408. End
  409.  
  410. Proc ShowEdges()
  411.     Variable b,x0,x1,p0,p1
  412.     String sx="W_ShowEstWidthsX",sy="W_ShowEstWidthsY"
  413.     WaveStats/Q $ampsY
  414.     Mk(sx,V_npnts*5+2);Mk(sy,V_npnts*5+2)
  415.     iterate (V_npnts)
  416.         b=i*5;p0=$edgsP[2*i];p1=$edgsP[2*i+1]
  417.         if(exists(g_wx)==1)
  418.             x0 =$g_wx[p0]
  419.             x1=$g_wx[p1]
  420.         else
  421.             x0=pnt2x($g_w,p0)
  422.             x1=pnt2x($g_w,p1)
  423.         endif
  424.         $sx[b,b+1]=x0
  425.         $sx[b+2,b+3]=x1
  426.         $sy[b,b+3]=0
  427.         $sy[b+1,b+2]=$ampsY[i]
  428.         if(exists(g_b)==1)
  429.             $sy[b,b+1]+=$g_b[p0]
  430.             $sy[b+2,b+3]+=$g_b[p1]
  431.         endif
  432.     loop
  433.     AppWv(sy,sx,"")
  434. End
  435.  
  436. Function/D MyBoxSmooth(w,pp,box)
  437.     Wave/D w
  438.     Variable pp,box | box should be odd
  439.     
  440.     Variable/D result=0
  441.     Variable  hp,top=numpnts(w)-1,terms
  442.     box = 2*trunc(box/2)+1
  443.     pp-=trunc(box/2)
  444.     hp=limit(0,pp+box-1,top)
  445.     pp=limit(0,pp,top)
  446.     terms=hp-pp+1
  447.     do
  448.         result+=w[pp]
  449.         pp+=1
  450.     while (pp<=hp)
  451.     return result/terms
  452. End
  453.  
  454. | W_PM[0]=n, number of functions to fit
  455. | W_PM[1]=start p of peak fit
  456. | W_PM[2]=end p of peak fit
  457. | W_PM[3]=tp, type of baseline
  458. | W_PM[4]=nw, baseline terms, could be 0
  459. | W_PM[5]=tp, type of 1st peak function
  460. |...
  461. | w[0]=NaN
  462. | w[1]=K0
  463. | w[2]=1st  coefficient...
  464. Function/D PolyMorph(w,xx)
  465.     Wave/D w
  466.     Variable/D xx
  467.     
  468.     Variable/D tp,nw, bs=3,n=W_PM[0],st=2,ii,s,r=w[1] | K0
  469.      if(n==0)
  470.         return r
  471.     endif
  472.     do    
  473.         tp=W_PM[bs]
  474.         nw=W_PM[bs+1]
  475.         if(nw>0)
  476.             if(tp<4) | line, poly 3 - poly 5 K1*x+K2*x^2...
  477.                 ii=nw-1
  478.                 s=0
  479.                 do
  480.                     s=w[ii+st]+xx*s
  481.                     ii-=1
  482.                 while (ii >= 0)
  483.                 r+= s*xx
  484.             else
  485.                 if(tp==7) | MyPeak
  486.                     ii=0
  487.                     do
  488.                         W_MyPkCoefs[ii]=w[ii+st]
  489.                         ii+=1
  490.                     while (ii < nw)
  491.                     r+=MyPeak(W_MyPkCoefs,xx)
  492.                 else
  493.                 if(tp==6) | exp
  494.                     r+= w[st]*exp(-w[st+1]*xx)
  495.                 else
  496.                 if(tp==5)    | dblexp
  497.                     r+= w[st]*exp(-w[st+1]*xx)*exp(-w[st+2]*xx)
  498.                 else    | 4, sin
  499.                     r+= w[st]*sin(w[st+1]*xx+w[st+2])
  500.                 endif
  501.                 endif
  502.                 endif
  503.             endif
  504.             st+=nw    
  505.         endif
  506.         bs+=2
  507.         n-=1
  508.     while (n>0)
  509.     return r
  510. End
  511.  
  512. Function MyCoefsToPeakSizes(cw)    | input cw, global outputs |MyPeak
  513.     Wave/D cw
  514.     |Variable/G/D V_ctr,V_amp,V_fwhm,V_area
  515.     V_ctr=cw[2]
  516.     V_amp=cw[0]*voigt(0,cw[3])
  517.     V_fwhm=1/cw[1]*(cw[3]+sqrt(cw[3]*cw[3]+4*ln(2))) | +/- 1%
  518.     V_area=cw[0]*sqrt(pi)/cw[1]
  519.     return 0
  520. End
  521.  
  522. Function MyPeakSizesToCoefs(ctr,amp,fwhm,y,cw)    |  output cw, for initial guesses
  523.     Variable/D ctr,amp,fwhm,y
  524.     Wave/D cw
  525.     y=y + (y==0)*0.05    | initial guess of zero not allowed
  526.     cw[0]=amp/voigt(0,y)
  527.     cw[1]=1/fwhm*(y+sqrt(y*y+4*ln(2))) | apprx
  528.     cw[2]=ctr
  529.     cw[3]=y
  530.     return 4    | #of cw terms
  531. End
  532.  
  533. Function/D MyPeak(w,x) | Voigt, 4 terms
  534.     Wave/D w
  535.     Variable/D x
  536.  
  537.     return w[0]*voigt(w[1]*(x-w[2]),w[3])
  538. End
  539.  
  540. Function/D voigt(x,y)
  541.     Variable/D x,y
  542.  
  543.     Variable/D i,j
  544.     Variable/D H= .201
  545.     Variable/D Y2,U,V,UU,VV,region,maxv,N,DX,minv
  546.     Y2= Y*Y
  547.     x= abs(x)
  548.     if( (x-5) >= 0 )
  549.         if( Y >= (11-.6875*X) )
  550.             region= 4;
  551.         else
  552.             region= 5
  553.         endif
  554.     else
  555.         if( (y-1) > 0 )
  556.             if( x > 1.85*(3.6-Y) )
  557.                 if( Y >= (11-.6875*X) )
  558.                     region= 4;
  559.                 else
  560.                     region= 5
  561.                 endif
  562.             else
  563.                 region= 2
  564.             endif
  565.         else
  566.             if( x+y >= 5 )
  567.                 region= 5
  568.             else
  569.                 region= 1
  570.             endif
  571.         endif
  572.     endif
  573.     if( region==1 )         | region I
  574.         N=  trunc(X/H)            | Fortran truncates
  575.         DX= X-W_HN[n]
  576.         U= (((W_D4[N]*Dx+W_D3[N])*Dx+W_D2[N])*DX+W_D1[N])*DX+W_D0[N]
  577.         V= 1-2*X*U
  578.         | Talyor series expansion about Y=0
  579.         VV= exp(y2-X*X)*cos(2*X*Y)/1.128379 - Y*V
  580.         UU= -Y
  581.         maxv= trunc(5+(12.5-X)*0.8*Y)
  582.         i= 1
  583.         do
  584.             U= (X*V+U)/W_RI[i]
  585.             V= (X*U+V)/W_RI[i+1]
  586.             UU= -UU*Y2
  587.             VV= VV+V*UU
  588.             i+=2
  589.         while(i<maxv)
  590.         return 1.12837*VV
  591.     endif
  592.     if( region==2 )         | region II
  593.         if( Y < 1.45 )
  594.             I= trunc(11*Y)
  595.         else
  596.             I= trunc(2*Y)
  597.         endif
  598.         j= trunc(x+x+1.85)
  599.         maxv=W_XN[j-1]*W_YN[i-1]+.46
  600.         minv= trunc(min(16,21-2*maxv))
  601.         | evaluate continued fraction
  602.         UU= Y
  603.         VV= X
  604.         j= minv-1
  605.         do
  606.             U= W_NBY2[j]/(UU*UU+VV*VV)
  607.             UU= Y+U*UU
  608.             VV= X-U*VV
  609.             j+=1
  610.         while(j<19)
  611.         return UU/(UU*UU+VV*VV)/1.772454
  612.     endif
  613.     
  614.     if( region==4 )         | region IIIb
  615.         U= X-.7071068
  616.         V= X+.7071068
  617.         return Y*(.2820948/(Y2+U*U)+.2820948/(Y2+V*V))
  618.     endif
  619.     if( region==5 )            | region iiia
  620.         U= X-.5246476
  621.         V= X+.5246476
  622.         UU= X-1.65068
  623.         VV= X+1.65068
  624.         return Y*(.2562121/(Y2+U*U)+.2562121/(Y2+V*V)+.02588268/(Y2+UU*UU)+.02588268/(Y2+VV*VV))
  625.     endif
  626. end
  627.  
  628. | This fits peak equations and a baseline equation or wave to the data.
  629. | If the baseline is removed, a constant baseline + peaks will be fit to the data.
  630. Macro FitPeaksAndBaseline(w,wx,extent,wb,wts)
  631.     String w=g_w,wx=g_wx,wb=fpks_b,wts=fpks_weights
  632.     Variable extent=fpks_extent
  633.     Prompt w,p_w,popup, WaveList("*",";","")
  634.     Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
  635.     Prompt extent,"extent of peak wave to fit",popup,"entire wave, all peaks;wave & peaks within cursors"
  636.     Prompt wb,p_b,popup, none+S_funcs+"_From Fit Baseline_;"+WaveList("*base*",";","")
  637.     Prompt wts,"weighting wave",popup, none+WaveList("*",";","")
  638.     
  639.     Silent 1;PauseUpdate
  640.     g_w=w;g_wx=wx;SBs(wb)
  641.     fpks_extent=extent;fpks_weights=wts
  642.     
  643.     ChkLen(w,wx);ChkLen(w,wb);ChkLen(w,wts)
  644.     ChkLen(ctrsX,ampsY);ChkLen(ctrsX,widsX)
  645.     Variable s=0,en=numpnts($w)-1
  646.     if(extent==2)
  647.         CheckTwoCursors(w)
  648.         s=V_start
  649.         en=V_theEnd
  650.     endif
  651.  
  652.     String tmpw="W_tmp",tw0="W_tmp0",ow="W_PeakFit"
  653.     Mk(pcw,5);Mk(pdcw,5)
  654.     Dup(w,ow);$ow=NaN
  655.     Variable terms=0,pkTyp=0,lim=1,baseTyp = floor(strsearch(S_funcs,wb,0)/10)
  656.     String cmd,opts=" /D="+ow
  657.     WaveStats/Q/R=[s,en] $w
  658.     Variable/D bsgs=V_avg,xdiff=pnt2x($w,en)-pnt2x($w,s)
  659.     if(bsgs==0)
  660.         bsgs=V_tol
  661.     endif
  662.     if(exists(wx)==1)
  663.         opts+=" /X="+wx
  664.         xdiff=$wx[en]-$wx[s]
  665.     endif
  666.     if(exists(wts)==1)
  667.         opts+="/W="+wts
  668.     endif
  669.     AppWv(ow,wx,"")
  670.     | initial baseline guesses
  671.     String hold
  672.     if(baseTyp>=0)| function selected (expect "_poly   1",  "_dblexp 5", etc)
  673.         terms=str2num(wb[7,8])-1 | exclude K0
  674.         cmd="CurveFit/Q/O "+wb[1,7]+", "+w+"[s,en] "+opts
  675.         Execute cmd
  676.         $pcw={NaN,K0,K1,K2,K3,K4}
  677.         $pdcw={1,s,en,baseTyp,terms}
  678.         hold="100000"[0,terms+1]
  679.         afp_b="_From Fit Peaks_"
  680.     else
  681.         if(exists(wb)==1)    | remove base before fit
  682.             Dup(w,tmpw);w=tmpw;$w-=$wb
  683.             terms=0;$pcw={NaN,0};$pdcw={1,s,en,0,0}
  684.             hold="11";bsgs=0 | K0 not varied
  685.         else
  686.             afp_b="_From Fit Peaks_"
  687.             if(cmpstr(wb,"_From Fit Baseline_")==0)    | Use base fit to start
  688.                 Dup(bcw,pcw);Dup(bdcw,pdcw)
  689.                 terms=$pdcw[4]
  690.                 $pdcw[1]=s;$pdcw[2]=en
  691.                 hold="100000"[0,terms+1]
  692.             else | _None_
  693.                 terms=0
  694.                 $pcw={NaN,bsgs}
  695.                 $pdcw={1,s,en,0,0}
  696.                 hold="10" |  K0 varied
  697.             endif
  698.         endif
  699.     endif
  700.     | prevent singular matrix w/ poly base
  701.     if($pdcw[3]<4)
  702.         $pcw[1,1+terms]=$pcw[p]*($pcw[p]!=0)+($pcw[p]==0)*bsgs/(xdiff^(p-1))
  703.     endif
  704.     WaveStats/Q $ctrsX
  705.     Variable npks=V_npnts
  706.     if(npks<1)
  707.         Abort "no peaks in peak center wave "+ctrsX
  708.     endif
  709.     Variable/D st=2+terms,dst,sz,dsz=2,pks=0,n
  710.     String/G holdTerms
  711.     Redimension/N=(5+npks*2) $pdcw
  712.     pkTyp= 7
  713.     sz=numpnts(W_MyPkCoefs)|MyPeak
  714.     holdTerms="00000000"[0,sz-1]
  715.     iterate (npks)
  716.         if(($ctrsP[i]>=s) %& ($ctrsP[i]<=en))
  717.             dst=3+dsz*$pdcw[0]
  718.             Redimension/N=(st+sz) $pcw
  719.             Mk(tw0,sz)
  720.             n= MyPeakSizesToCoefs($ctrsX[i],$ampsY[i],$widsX[i],W_EstY[i],$tw0)    |  output $tw0, for initial guesses
  721.             $pcw[st,st+sz-1]=$tw0[p-st]
  722.             $pdcw[dst]=pkTyp
  723.             $pdcw[dst+1]=sz
  724.             hold+= holdTerms
  725.             st+=sz
  726.             $pdcw[0]+=1
  727.             pks+=1
  728.         endif
  729.     loop
  730.     if(pks<1)
  731.         Abort "no peaks between cursors"
  732.     else
  733.         Print "Fitting ",pks," peaks"
  734.     endif
  735.     | Fit peaks using initial guesses for coefficients
  736.     Dup(pdcw,"W_PM")
  737.     cmd="FuncFit/H=hold  PolyMorph $pcw,$w[s,en]"+opts
  738.     ResumeUpdate
  739.     Execute cmd        | FuncFit… ("singular matrix…" usually means normalize x values!)
  740.     KillWv(tmpw)
  741.     if(exists(wb)==1)
  742.         $ow[s,en]+=$wb[p]
  743.     endif
  744.     ar_wfit=ow
  745.     ar_ex=extent
  746.     g_keep=w
  747. End
  748.  
  749. Macro Report(title,srt,order,basInf)
  750.     String title=pfr_title, srt=pfr_sort,
  751.     Variable order=pfr_order,basInf=pfr_bi
  752.     Prompt title,"report title"
  753.     Prompt srt,"sort report by",popup,"center;amplitude;width;area"
  754.     Prompt order,"sort order",popup,"ascending;descending"
  755.     Prompt basInf,"baseline info",popup,"include;omit"
  756.     
  757.     Silent 1
  758.     pfr_title=title;pfr_sort=srt;pfr_order=order;pfr_bi=basInf
  759.     String center="W_PkCenters",amplitude="W_PkAmps",width="W_PkFWHMs",area="W_PkAreas",tw2="W_tmp2"
  760.  
  761.     Variable terms=$pdcw[4],btyp=$pdcw[3] | baseline terms, not counting K0
  762.     Variable sz=3,dsz=2,st=2+terms,dst=5,n
  763.     Variable npks=$pdcw[0]-1,np1=npks-1,nrows=max(2,npks)
  764.     String text=num2istr(npks),extra=""
  765.     Mk(center,nrows);Mk(amplitude,nrows);Mk(width,nrows);Mk(area,nrows);Mk("W_PkY",nrows)
  766.     if(npks<1)
  767.         Abort "no peaks"
  768.     endif
  769.     DoWindow/F PeakFitGraph
  770.     if(V_Flag==0)
  771.         AppWv(g_w,g_wx,"");AppWv("W_PeakFit",wx,"");ColorWaves();DoWindow/C PeakFitGraph
  772.     else
  773.         NoCrs()
  774.     endif
  775.     
  776.     DoWindow/F PeakReportTable
  777.     if(V_Flag==0)
  778.         PeakReportTable()
  779.     endif
  780.  
  781.     | Separate the coefficients into separate waves
  782.     Variable pkTyp=$pdcw[5]
  783.     if(pkTyp==7) | MyPeak
  784.         sz=numpnts(W_MyPkCoefs);extra=",W_PkY";Mk("W_PkY",nrows) |MyPeak
  785.         Mk(tw2,sz)
  786.         iterate (npks)
  787.             $tw2=$pcw[st+p]
  788.             n=MyCoefsToPeakSizes($tw2)
  789.             $center[i]=V_ctr;$amplitude[i]=V_amp;$width[i]=V_fwhm;$area[i]=V_area
  790.             W_PkY[i]=$pcw[st+3]
  791.             st += sz
  792.         loop
  793.         text+=" Voigt Peaks" | MyPeak
  794.     else
  795.         Abort "Unsupported Peak type"
  796.     endif
  797.     String cmd="Sort "
  798.     if(order==2)
  799.         cmd+="/R  "
  800.     endif
  801.     cmd+="$"+srt+",$center,$amplitude,$width,$area"+extra
  802.     Execute cmd        | Sort...
  803.     
  804.     DoWindow/F PeakReportLayout
  805.     if(V_Flag==0)
  806.         PeakReportLayout()
  807.     endif
  808.     if((basInf==1)%&(terms>0)%&(btyp>=0))
  809.         text+="\r\rBaseline function: "+S_funcs[btyp*10+1,btyp*10+7]
  810.         text+="\r\tK0 = "+num2str($pcw[1])
  811.         iterate (terms)
  812.             text+="\r\tK"+num2istr(i+1)+"= "+num2str($pcw[2+i])
  813.         loop
  814.     endif
  815.     ReplaceText/N=info text
  816.     ReplaceText/N=title "\JC"+title
  817.     Modify rows(PeakReportTable)=nrows
  818. End
  819.  
  820. Macro ShowFittedPeaks(w,wx,wb,pks,anno)
  821.     String w=g_w,wx=g_wx,wb=afp_b
  822.     Variable pks=afp_pks,anno=afp_anno
  823.     Prompt w,p_w,popup, WaveList("*",";","")
  824.     Prompt wx,p_wx,popup,calc+WaveList("*X", ";","")
  825.     Prompt wb,p_b,popup, none+"_From Fit Peaks_;"+WaveList("*base*",";","")
  826.     Prompt pks,"peak waves",popup,"off;on"
  827.     Prompt anno,"peak annotation tags",popup, "off;on"
  828.  
  829.     Silent 1;PauseUpdate
  830.     g_w=w;g_wx=wx;afp_anno=anno;afp_pks=pks;SBs(wb)
  831.     ChkLen(w,wx);ChkLen(w,wb)
  832.     String tdcw="W_PM",tcw="W_tmp",pkw,text,typ,tw2="W_tmp2"
  833.     if ((pks==1)%&(anno==1))
  834.         DoAlert 0,"Both tags and peaks are off!"
  835.     endif
  836.     if(numtype($pdcw[1])!=0)
  837.         Abort "Run FitPeaks first!"
  838.     endif
  839.     Variable s=$pdcw[1],en=$pdcw[2],terms,sz
  840.     sz=numpnts(W_MyPkCoefs)
  841.     Dup(pdcw,tdcw);Dup(pcw,tcw)
  842.     if(cmpstr(wb,"_From Fit Peaks_") == 0)
  843.         terms=$pdcw[4]
  844.         Redimension/N=(5+2) $tdcw;$tdcw[0]=2
  845.     else
  846.         $tdcw={2,s,en,0,0,NaN,sz}
  847.         $tcw={NaN,0}
  848.         terms = 0
  849.     endif
  850.     Variable dsz=2,st=2+terms,cst=2+$pdcw[4],dcst=5,n,y,npks=$pdcw[0]-1
  851.     Redimension/N=(st+sz) $tcw
  852.     iterate (npks)
  853.         $tcw[st,st+sz-1]=$pcw[cst+p-st]
  854.         $tdcw[5,6]=$pdcw[dcst+p-5]
  855.          if (pks==2)
  856.             NewWv(w,"_fpk");pkw=S_Wave;$pkw=NaN
  857.             if(exists(wx)==1)
  858.                 $pkw[s,en]=PolyMorph($tcw,$wx[p])
  859.             else
  860.                 $pkw[s,en]=PolyMorph($tcw,x)
  861.             endif
  862.             if(exists(wb)==1)
  863.                 $pkw[s,en]+=$wb[p]
  864.             endif
  865.             AppWv(pkw,wx,"");Modify mode($pkw)=1
  866.         endif
  867.         if($pdcw[5]==7) |MyPeak
  868.             typ="\JCVoigt\r"
  869.             Mk(tw2,sz)
  870.             $tw2=$tcw[st+p]
  871.             n=MyCoefsToPeakSizes($tw2)
  872.             y=$tcw[st+3]
  873.         else
  874.             Abort "Unsupported peak type"
  875.         endif
  876.         sprintf text, "\JL\Z09amp=%g\rcenter=%g\rwidth(+/-1%%)=%g\rarea=%g\ry=%g",V_amp,V_ctr,V_fwhm,V_area,y
  877.          if(anno==2)
  878.             FindPX(w,wx,V_ctr)
  879.             Tag/C/N=$("peak"+num2istr(g_ptgn))/A=MC  $w, V_peakX, typ+text
  880.             g_ptgn+=1
  881.         endif
  882.         dcst+=dsz;cst+=sz
  883.     loop
  884. End
  885.  
  886. Macro HideFittedPeaks()
  887.     Silent 1;PauseUpdate
  888.     String w,ws=WaveList("*_fpk",";","WIN:"+WinName(0,1))
  889.     Variable pos
  890.     do
  891.         pos=strsearch(ws,";",0)
  892.         if(pos<0)
  893.             break
  894.         endif
  895.         w=ws[0,pos-1]
  896.         ws[0,pos]=""
  897.         RmWv(w);KillWv(w)
  898.     while (1)
  899.     do
  900.         Tag/K/N=$("peak"+num2istr(g_ptgn))
  901.         g_ptgn-=1
  902.     while (g_ptgn>=0)
  903.     g_ptgn=0
  904.     ColorWaves()
  905. End
  906.  
  907. Proc FindPX(w,wx,xx)
  908.     String w,wx    | wx monotonic
  909.     Variable xx
  910.  
  911.     if(exists(wx)==1)
  912.         FindLevel/Q $wx, xx 
  913.         V_peakP = x2pnt($wx,V_levelX)
  914.         if(V_Flag==1)
  915.             if((xx<$wx[1])%&($wx[0]<$wx[1]))
  916.                 V_peakP=0
  917.             else
  918.                 V_peakP=numpnts($w)-1
  919.             endif        
  920.         endif
  921.         V_peakX = pnt2x($w,V_peakP)
  922.     else
  923.         V_peakP = x2pnt($w,xx)
  924.         V_peakX = xx
  925.     endif
  926. End
  927.  
  928. Proc ChkLen(w1,w2)
  929.     String w1,w2    | Wave names
  930.     if((exists(w1)==1) %& (exists(w2)==1))
  931.         if(numpnts($w1) != numpnts($w2))
  932.             Abort w1+" and "+w2+" have different number of points!"
  933.         endif
  934.     endif
  935. End
  936.  
  937. Proc Mk(w,n)
  938.     String w
  939.     Variable n
  940.     if(exists(w)==1)
  941.         Redimension/D/N=(n) $w;$w=NaN
  942.     else
  943.         Make/D/N=(n) $w=NaN
  944.     endif    
  945. End
  946.  
  947. Proc Dup(t,w)
  948.     String t,w
  949.     String n=""
  950.     if (exists(w)==1)
  951.         n=note($w) | keep w's note
  952.     endif
  953.     Duplicate/O $t,$w;Note/K $w
  954.     if( strlen(n)>0)
  955.         Note $w,n
  956.     endif
  957. End    
  958.  
  959. Proc SameLen(t,w)
  960.     String t,w
  961.     if(exists(w)!=1)
  962.         Duplicate/O $t,$w
  963.     else
  964.         Redimension/D/N=(numpnts($t)) $w;CopyScales $t,$w
  965.     endif
  966. End    
  967.  
  968. Proc NewWv(srcw,sfx)
  969.     String srcw,sfx
  970.  
  971.     Variable ii=1
  972.     S_Wave=srcw[0,17-strlen(sfx)]+sfx
  973.     if(exists(S_Wave)==1)
  974.         String shw=S_Wave
  975.         do
  976.             S_Wave=srcw[0,14-strlen(sfx)]+num2istr(ii)+sfx
  977.             ii+=1
  978.         while ((exists(S_Wave)==1)*(ii<999))
  979.     endif
  980.     if(exists(srcw)==1)
  981.         Duplicate/O $srcw,$S_Wave
  982.     else
  983.         Make/D/O $S_Wave
  984.     endif
  985.     Print "Created wave "+S_Wave
  986. End
  987.  
  988. Proc RmWv(w)
  989.     String w
  990.  
  991.     CheckDisplayed/W=$WinName(0,1) $w
  992.     if(V_Flag==1)
  993.         DoWindow/F $WinName(0,1);Remove $w
  994.     endif
  995. End
  996.  
  997. Proc KillWv(w)
  998.     String w
  999.     if(exists(w)==1)
  1000.         CheckDisplayed/A $w
  1001.         if(V_Flag==0)
  1002.             KillWaves $w
  1003.         endif
  1004.     endif
  1005. End
  1006.  
  1007. Proc AppCrs(w)
  1008.     String w
  1009.     ShowInfo;Cursor/P A,$w,0;Cursor/P B,$w,numpnts($w)-1
  1010. End
  1011. Proc NoCrs()
  1012.     HideInfo;Cursor/K A;Cursor/K B
  1013. End
  1014. Proc AppWv(w,wx,ax)
  1015.     String w,wx,ax
  1016.     
  1017.     String wn=WinName(0,1)
  1018.     if(strlen(wn)==0)
  1019.         ax = "Display $w"
  1020.     else
  1021.         DoWindow/F $wn
  1022.         ax="Append"+ax+" $w "
  1023.     endif
  1024.     if(exists(w)==1)
  1025.         CheckDisplayed $w
  1026.         if(V_Flag==0)
  1027.             if(exists(wx)==1)
  1028.                 ax+=" vs $wx"
  1029.             endif
  1030.             Execute ax
  1031.             ColorWaves()
  1032.         endif
  1033.     endif
  1034. End
  1035. Proc SBs(s)
  1036.     String s
  1037.     if((exists(s)==1)%|(cmpstr(s+";",none)==0))
  1038.         g_b=s;rb_b=s;fpks_b=s;afp_b=s
  1039.     else
  1040.     if(strsearch(S_funcs,s,0)>=0)
  1041.         fpks_b=s
  1042.     else
  1043.     if(cmpstr(s,"_From Fit Peaks_")==0)
  1044.         rb_b=s;afp_b=s
  1045.     else
  1046.     if(cmpstr(s,"_From Fit Baseline_")==0)
  1047.         fpks_b=s
  1048.     endif
  1049.     endif
  1050.     endif
  1051.     endif
  1052. End
  1053. Macro ShowFitResidual(w,wx,wfit,ow,extent,anno)
  1054.     String w=g_w,wx=g_wx,wfit=ar_wfit,ow=ar_ow
  1055.     Variable anno=ar_anno,extent=ar_ex
  1056.     Prompt w,p_wd,popup, WaveList("*",";","")
  1057.     Prompt wx,p_wxd,popup,calc+WaveList("*X", ";","")
  1058.     Prompt wfit,"fit wave",popup, WaveList("*Fit",";","")
  1059.     Prompt ow,"output residual wave",popup,new+WaveList("*",";","")
  1060.     Prompt extent,"extent of residual wave to measure",popup,"entire wave;between cursors;"+breg
  1061.     Prompt anno,"standard deviation lines annotations",popup,"± 1; ± 2;"+none
  1062.  
  1063.     Silent 1;PauseUpdate
  1064.     String wf=wfit[2,5]
  1065.     if(exists(ow)!=1)
  1066.         NewWv(w,wf+"Res");ow=S_Wave
  1067.     else
  1068.         SameLen(w,ow)
  1069.     endif
  1070.     g_w=w;g_wx=wx;ar_wfit=wfit;ar_ow=ow;ar_ex=extent;ar_anno=anno
  1071.     ChkLen(w,wx);ChkLen(w,wfit)
  1072.     Variable s=0,en=numpnts($w)-1
  1073.     if(extent==2) | use cursors
  1074.         CheckTwoCursors(w)
  1075.         s=V_start
  1076.         en =V_theEnd
  1077.     endif
  1078.     if(extent==3)
  1079.         if(exists(breg)!=1)
  1080.             Abort breg+" doesn't exist!"
  1081.         endif
  1082.         ChkLen(w,breg)
  1083.         $ow=($w[p]-$wfit[p]) / (numtype($breg[p])==0)
  1084.     else
  1085.         $ow=NaN;$ow[s,en]=$w[p]-$wfit[p]
  1086.     endif
  1087.     
  1088.     WaveStats/R=[s,en] $ow
  1089.     String rx="W_Resid"+wf+"X",ry="W_Resid"+wf+"Y"
  1090.     if(anno<3)
  1091.         Mk(rx,6);Mk(ry,6)
  1092.         if(exists(wx)==1)
  1093.             $rx[0,;4]=$wx[s]
  1094.             $rx[1,;4]=$wx[en]
  1095.         else
  1096.             $rx[0,;4]=pnt2x($w,s)
  1097.             $rx[1,;4]=pnt2x($w,en)
  1098.         endif
  1099.         $ry[0,;4]=(trunc(p/2)-1)*V_sdev*anno
  1100.         $ry[1,;4]=$ry[p-1]
  1101.         AppWv(ry,rx,"/R")
  1102.         Variable maxv=max(V_max,anno*V_sdev),minv=min(V_min,-anno*V_sdev)
  1103.         Modify zero(right)=1,minor(right)=1
  1104.         SetAxis right minv-3*(maxv-minv),maxv
  1105.     endif
  1106.     AppWv(ow,wx,"/R");Modify mode($ow)=3,marker($ow)=8,msize($ow)=1
  1107.     Label right "Residual (fit-data)"
  1108. End
  1109.  
  1110. Macro ShowOnlyDataAndBase()
  1111.     Silent 1;PauseUpdate
  1112.     String keep=g_w+";"+g_wx+";"
  1113.     keep+=g_b+";"+WaveList("*X",";","WIN:"+WinName(0,1))
  1114.     keep+=g_keep+";";g_keep=""
  1115.     String w,wn=WinName(0,1),ws=WaveList("*",";","WIN:"+wn)
  1116.     Variable pos,flg=0
  1117.     if(strlen(wn)!=0)
  1118.         do
  1119.             pos=strsearch(ws,";",0)
  1120.             if(pos<0)
  1121.                 break
  1122.             endif
  1123.             w=ws[0,pos-1]
  1124.             ws[0,pos]=""
  1125.             if(strsearch(keep,w+";",0)<0)
  1126.                 RmWv(w);flg=1
  1127.             endif
  1128.         while (1)
  1129.         if(flg)
  1130.             ColorWaves()
  1131.         endif
  1132.     endif
  1133. End
  1134.  
  1135. Macro ColorWaves() : GraphStyle
  1136.     Silent 1;PauseUpdate
  1137.     Modify/Z lSmooth=1,lHair=0.5,minor(bottom)=1
  1138.     Modify/Z rgb[0]=(65535,0,0)
  1139.     Modify/Z rgb[1]=(0,0,65535),rgb[2]=(3009,65535,1882),rgb[3]=(0,0,0)
  1140.     Modify/Z rgb[4]=(0,0,65535),rgb[5]=(63953,3661,65535)
  1141.     Modify/Z rgb[6]=(37510,1,1),rgb[7]=(27232,40528,22540),rgb[8]=(1531,1314,28456)
  1142.     Legend/C/N=default ""
  1143. End
  1144.  
  1145.  
  1146. Proc CheckTwoCursors(w)
  1147.     String w    | the y wave
  1148.     Variable/G V_start,V_theEnd,V_startX,V_theEndX | point indices, x vals
  1149.     String wa=CsrWave(A),wb=CsrWave(B),t="cursors on target graph "
  1150.     if((strlen(wa)==0)%|(strlen(wb)==0))
  1151.         Abort "expecting two "+t
  1152.     endif
  1153.     V_start=pcsr(A);V_theEnd=pcsr(B)
  1154.     V_startX=hcsr(A);V_theEndX=hcsr(B)
  1155.     Variable x0=pnt2x($w,0),x1=pnt2x($w,1),ok
  1156.     ok = (numpnts($wa)==numpnts($w)) %& (numpnts($wb)==numpnts($w)) 
  1157.     ok = ok %& (x0==pnt2x($wa,0)) %& (x1==pnt2x($wa,1))
  1158.     ok = ok %& (x0==pnt2x($wb,0)) %& (x1==pnt2x($wb,1)) 
  1159.     if(ok)
  1160.         if(V_start>V_theEnd)
  1161.             x0=V_Start
  1162.             V_start=V_theEnd
  1163.             V_theEnd=x0
  1164.             x0=V_startX
  1165.             V_startX=V_theEndX
  1166.             V_theEndX=x0
  1167.         endif
  1168.         if(V_start==V_theEnd)
  1169.             Abort t+"are too close together!"
  1170.         endif
  1171.     else
  1172.         Abort t+"must be on wave "+w+" or one like it"
  1173.     endif
  1174. End
  1175.  
  1176. Window DefinePeaks() : Table
  1177.     PauseUpdate; Silent 1        | building window...
  1178.     Edit W_MakeCentersX.y,W_MakeAmpsY.y,W_MakeWidthsX.y as "DefinePeaks"
  1179.     Append W_My.y
  1180. EndMacro
  1181.  
  1182. Window PeakEstimates() : Table
  1183.     PauseUpdate; Silent 1        | building window...
  1184.     Edit  W_EstCentersP.y,W_EstCentersX.y,W_EstAmpsY.y as "Peak Estimates"
  1185.     Append W_EstWidthsX.y,W_EstEdgesP.y,W_EstY.y
  1186.     Modify width(Point)=64
  1187. EndMacro
  1188.  
  1189. Window PeakReportTable() : Table
  1190.     PauseUpdate; Silent 1        | building window...
  1191.     Edit W_PkCenters.y,W_PkAmps.y,W_PkFWHMs.y,W_PkAreas.y,W_PkY
  1192. EndMacro
  1193.  
  1194. Window PeakReportLayout() : Layout
  1195.     PauseUpdate; Silent 1        | building window...
  1196.     Layout /W=(3,40,500,327) PeakReportTable(62,394,538,444)/O=2 as "Peak Report Layout"
  1197.     Textbox /N=title/A=LT/X=39.6364/Y=5.21978 "\JCYour Report Title Here"
  1198.     Modify left(title)=249,top(title)=70,width(title)=109,height(title)=8,frame(title)=4
  1199.     Textbox /N=info/A=LT/X=38.9091/Y=43.6813 "2 Voigt Peaks\r\rBaseline function: line   "
  1200.     AppendText "\tK0 = -273.8\r\tK1= 1.0544e+09"
  1201.     Modify left(info)=245,top(info)=350,width(info)=116,height(info)=44,frame(info)=1
  1202.     Append PeakFitGraph(63,116,555,325)/O=1
  1203. EndMacro
  1204.  
  1205.